{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Probability Distributions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "author: Jacob Schreiber <br>\n",
    "contact: jmschreiber91@gmail.com"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial will cover the various distributions that are implemented in pomegranate. These distributions can be used by themselves, or more typically as a part of a larger compositional model like a hidden Markov model. \n",
    "\n",
    "The distributions that are currently available:\n",
    "\n",
    "Univariate Distributions\n",
    "    1. BernoulliDistribution\n",
    "    2. BetaDistribution\n",
    "    3. DiscreteDistribution\n",
    "    4. ExponentialDistribution\n",
    "    5. GammaDistribution\n",
    "    6. LogNormalDistribution\n",
    "    7. NormalDistribution\n",
    "    8. PoissonDistribution\n",
    "    9. UniformDistribution\n",
    "  \n",
    "Univariate Kernel Densities\n",
    "    1. GaussianKernelDensity\n",
    "    2. UniformKernelDensity\n",
    "    3. TriangleKernelDensity\n",
    "  \n",
    "Multivariate Distributions\n",
    "    1. IndependentComponentsDistribution\n",
    "    2. Dirichlet Distribution\n",
    "    3. MultivariateGaussianDistribution\n",
    "    4. ConditionalProbabilityTable\n",
    "    5. JointProbabilityTable\n",
    "\n",
    "The following methods are supported by all distributions:\n",
    "\n",
    "```\n",
    "1. d.probability(X): Return the probability of a sample under the distribution or a vector of samples\n",
    "2. d.log_probability(X): Return the log probability of a sample under the distribution or a vector of samples\n",
    "3. d.fit(X, weights=None, inertia): Use MLE estimates to update the parameters of the distribution. Optional weight vector is accepted, or inertia that pushes parameters from where they currently are to the update that portion of the way.\n",
    "4. d.summarize(X, weights=None): Extract and update the stored sufficient statistics on a data set with optional weights, but don't update the parameters yet\n",
    "5. d.from_summaries(X, inertia=0.0): Use the stored sufficient statistics to do a parameter update\n",
    "6. d.sample(n=1): Generate a sample, or a vector of samples, from the distribution\n",
    "\n",
    "7. d.to_json(): Serialize the distribution to a string json\n",
    "8. Distribution.from_json(s): Load up a stored distriibution, either from a file if passed a filename that ends in '.json', or from the string passed in itself.\n",
    "\n",
    "9. d.copy(): Make a deep copy of the distribution\n",
    "10. d.freeze(): Freeze the distribution, making 'fit' and 'from_summaries' not change model parameters\n",
    "11. d.thaw(): Unfreeze the distribution so that it can be updated agin.\n",
    "```\n",
    "\n",
    "Univariate distributions also have a `plot(n=1000, **kwargs)` command, where you can plot a histogram of `n` randomly generated samples from the distribution, which will pass matplotlib keyword arguments to the `plt.hist` function. \n",
    "\n",
    "Lets look at a few examples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fri Jan 10 2020 \n",
      "\n",
      "numpy 1.18.1\n",
      "scipy 1.4.1\n",
      "pomegranate 0.12.0\n",
      "\n",
      "compiler   : Clang 10.0.0 (clang-1000.11.45.5)\n",
      "system     : Darwin\n",
      "release    : 17.7.0\n",
      "machine    : x86_64\n",
      "processor  : i386\n",
      "CPU cores  : 4\n",
      "interpreter: 64bit\n"
     ]
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn; seaborn.set_style('whitegrid')\n",
    "import numpy\n",
    "\n",
    "from pomegranate import *\n",
    "\n",
    "numpy.random.seed(0)\n",
    "numpy.set_printoptions(suppress=True)\n",
    "\n",
    "%load_ext watermark\n",
    "%watermark -m -n -p numpy,scipy,pomegranate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The API\n",
    "\n",
    "### Initialization\n",
    "\n",
    "Let's first look at an example of using the methods in the API. First, we can create probability distributions by passing in the parameters if we know them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = NormalDistribution(5, 2)\n",
    "d2 = ExponentialDistribution(5)\n",
    "d3 = LogNormalDistribution(2, 0.4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If what you have is data and you'd like to fit your distribution to the data, rather than having parameters beforehand, you can use the `from_samples` class method to pass in the points and optional weights."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = numpy.random.normal(10, 1, size=100)\n",
    "\n",
    "d4 = NormalDistribution.from_samples(x)\n",
    "d5 = ExponentialDistribution.from_samples(x)\n",
    "d6 = LogNormalDistribution.from_samples(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If the data is univariate we can pass in a simple vector. If our data is multivariate and we'd like to fit a multivariate distribution we can pass in a matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([9.94235563, 9.96112858, 9.99785915]),\n",
       " array([[ 0.98534191, -0.01989778, -0.03028855],\n",
       "        [-0.01989778,  0.95247322,  0.0396411 ],\n",
       "        [-0.03028855,  0.0396411 ,  0.88819551]]))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = numpy.random.normal(10, 1, size=(1000, 3))\n",
    "\n",
    "d7 = MultivariateGaussianDistribution.from_samples(x)\n",
    "d7.mu, d7.cov"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we want to model our multivariate data with a different distribution on each feature, assuming that each feature is independent of each other, we can use an IndependentComponentsDistribution. This can be done either by passing in the distributions to the initialization, or as `from_samples`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" : \"Distribution\",\n",
       "    \"name\" : \"IndependentComponentsDistribution\",\n",
       "    \"parameters\" : [\n",
       "        [\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"NormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    10.05980801553448,\n",
       "                    1.0078822447166023\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"ExponentialDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    0.09940547566677038\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"LogNormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    2.303462554064328,\n",
       "                    0.1012880395101563\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            }\n",
       "        ],\n",
       "        [\n",
       "            1.0,\n",
       "            1.0,\n",
       "            1.0\n",
       "        ]\n",
       "    ],\n",
       "    \"frozen\" : false\n",
       "}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d8 = IndependentComponentsDistribution([d4, d5, d6])\n",
    "d8"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we wanted to learn a multivariate Gaussian distribution but with a forced diagonal covariance matrix we can model each feature are independent normal distributions, like such."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" : \"Distribution\",\n",
       "    \"name\" : \"IndependentComponentsDistribution\",\n",
       "    \"parameters\" : [\n",
       "        [\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"NormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    9.942355632560583,\n",
       "                    0.9926439000824223\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"NormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    9.96112857784113,\n",
       "                    0.9759473472188426\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"NormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    9.997859147101435,\n",
       "                    0.9424412506637966\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            }\n",
       "        ],\n",
       "        [\n",
       "            1.0,\n",
       "            1.0,\n",
       "            1.0\n",
       "        ]\n",
       "    ],\n",
       "    \"frozen\" : false\n",
       "}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d8.from_samples(x, distributions=NormalDistribution)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the distributions here are displaying the mean and standard deviation, whereas the `MultivariateGaussianDistribution` is showing the mean and ~covariance~, which is the standard deviation squared. When adjusted accordingly, the means here line up with the vector of means from before, and the standard deviations are equal to the square root of the diagonal of the covariance matrix.\n",
    "\n",
    "Lastly, if we wanted to learn an independent components distribution with different distributions on each feature, we can pass in a list of distributions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" : \"Distribution\",\n",
       "    \"name\" : \"IndependentComponentsDistribution\",\n",
       "    \"parameters\" : [\n",
       "        [\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"NormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    9.942355632560583,\n",
       "                    0.9926439000824223\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"ExponentialDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    0.10039023111442362\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"LogNormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    2.297868979078352,\n",
       "                    0.09529758318186476\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            }\n",
       "        ],\n",
       "        [\n",
       "            1.0,\n",
       "            1.0,\n",
       "            1.0\n",
       "        ]\n",
       "    ],\n",
       "    \"frozen\" : false\n",
       "}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d8.from_samples(x, distributions=[NormalDistribution, ExponentialDistribution, LogNormalDistribution])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plotting\n",
    "\n",
    "If we want to visualize them, we can use the plot command, which randomly draws samples from the model and plots the histogram of those samples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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MHv2bLx69QqampoIDg6GpaVlpcRU3DGj6roqLabLly9j7dq1WL16tfg3Dx48ELuY165dGxEREWL3V2UqeEwfOnQIr169wrBhw8RRBAVBwEcffYSRI0fi9evXlX5MF4zLxsYGH330ERwdHcVG+ahRo9CjR49KOaaLqyt531mVWVc1jbzvYnXP0cVR5DuzuihYloSEBISHh0NbWxv169dHeHi4TDdodSbvHHTu3LmIiIiolttGXnmmT5+OpUuXlnv7qGUDi4iIiIiIqDpSyy6CRERERERE1REbWERERERERErCBhYREREREZGSsIFFRERERESkJGxgERERERERKQkbWERERERERErCBhYREREREZGSsIFFRERERESkJGxgERERERERKQkbWERERERERErCBhYREREREZGSsIFFRERERESkJGxgqVDv3r1hZWVV5GfgwIEAAH9/f8yaNQsAIAgCvv/+e0ilUrnrioqKQps2bXDjxg25n7N7927VFaQMrKyscPr0abnzvLy8ZOqhXbt2cHNzQ0xMjMxyipYnIyMD+/btK3b+mTNnYGVlhZycHCQnJ8PKygr37t0rW4H+X1ZWFnbs2CFTli+//LJc6yIqjrJzhrx1WVlZ4bPPPqu0MqlC4WO/LDmQOYpIubmm4LKqln/MbNu2rUrjKE1Jx1/h3GxjYwNnZ2esWLEC2dnZ4nKKlqe07QPI5r2KnjMePXoUqampYlk8PDzKva6aTKuqA6jp/P39xYSVT0srr9rnzp0rTjt37hzmz58Pd3d3aGjIb/fm5ORg/vz52L59OyQSieqCVqHRo0dj/PjxEAQBaWlpOH78OAICApCTk4MPP/wQALBnzx7o6emVuq5vvvkGp06dEv+uMHt7e8TFxYn1XRE//PADVq9ejeHDhwPISyra2toVXi9RYcrMGba2tli9enWR6bq6ukqMuPIVPvYVzRmKYI6it4Uyc01l++qrr9CvXz+8++67VR1KuRTMzW/evMGVK1ewYMECPH78GIsXLwYguw1Kosj2iYuLwzvvvFPhuB8+fIhp06bh559/BgB4e3vDy8urwuutidjAUjEDAwMYGxvLnWdoaCj+XxCEUtfVoEEDXL58GXv37sXHH3+stBgrU+3atcX6aNCgASwtLfHq1SssXboUAwYMgK6uLurVq6fQukqrMx0dnWLrvqwKf5aRkZFS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\n",
      "text/plain": [
       "<Figure size 864x288 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(12, 4))\n",
    "plt.subplot(231)\n",
    "plt.title(\"Normal Distribution\", fontsize=14)\n",
    "d.plot(1000, edgecolor='c', color='c', bins=20)\n",
    "\n",
    "plt.subplot(232)\n",
    "plt.title(\"Exponential Distribution\", fontsize=14)\n",
    "d2.plot(1000, edgecolor='m', color='m', bins=20)\n",
    "\n",
    "plt.subplot(233)\n",
    "plt.title(\"Log Normal Distribution\", fontsize=14)\n",
    "d3.plot(1000, edgecolor='g', color='g', bins=20)\n",
    "\n",
    "plt.subplot(234)\n",
    "plt.title(\"Fit Normal Distribution\", fontsize=14)\n",
    "d4.plot(1000, edgecolor='c', color='c', bins=20)\n",
    "\n",
    "plt.subplot(235)\n",
    "plt.title(\"Fit Exponential Distribution\", fontsize=14)\n",
    "d5.plot(1000, edgecolor='m', color='m', bins=20)\n",
    "\n",
    "plt.subplot(236)\n",
    "plt.title(\"Fit Log Normal Distribution\", fontsize=14)\n",
    "d6.plot(1000, edgecolor='g', color='g', bins=20)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Naturally, if you wanted smoother probability distributions, you could calculate the probability at each point along a given grid and plot those probabilities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+4AAADQCAYAAACZfDv+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nOzdd3gU5drH8e9mk02l9xYICKFJV/AoKkVRQDE2iBJQULFyVESKSJfyesQSqgcRBRWQooiIiqKAICV0SCghgdCSkEa2ZNvM+0fMnmxII2Szm+T+XFcukp3Z3d8MO8/OPfPMMxpVVVWEEEIIIYQQQgjhkbzcHUAIIYQQQgghhBAFk8JdCCGEEEIIIYTwYFK4CyGEEEIIIYQQHkwKdyGEEEIIIYQQwoNJ4S6EEEIIIYQQQngwKdyFEEIIIYQQQggPJoV7JdO7d2+efPJJ8t4FcM+ePYSGhmKz2dyU7H/Wr1/P3Xffne+0CxcuEBoa6vhp06YN3bt35+WXXyY+Pt4x340sT3R0NPv37y9w+vjx43nrrbcAiIyMJDw8/MYWKJeEhAT++OMPp2U5d+5ciV9PCFF8vXv3dmo/cv9s3brV3fFuSu527EbaP2lvhRBFCQ0NZdeuXWXyXuPHj6dr164kJye7NUdhimpPcn/XtG7dms6dOzNkyBB27NjhNF9xlyclJYXNmzcXOD13O36z+/MGg4H169c7Lcu3335botcSpU8K90ro8OHDrFmzxt0xbsrq1avZuXMn27Zt49NPP8VisTB06FCSkpIA6Ny5Mzt37sTb27vI13rllVeIi4srcPo777zDlClTSiX3xIkTOXjwIAANGjRg586dNG7cuFReWwhRtPHjx7Nz587rfgoqXsuL3O3YjbR/xSHtrRCiLOn1eubMmePuGDcl57vmzz//ZPXq1XTp0oVRo0Y5Feo7d+6kW7duRb7Wf/7zH37//fcCp/fv35/vvvuuVHJ//vnnToX62rVreeihh0rltcXNk8K9EmrUqBHz5s0jNTXV3VFKrEaNGtSpU4f69evTsWNHFixYQEBAAEuWLAFAp9NRp06dUnmvKlWqUKVKlVJ5rdy0Wi116tRBq9WW+msLIfIXFBREnTp1rvvR6XTujlZqSrP9A2lvhRBlq1GjRmzatIndu3e7O0qJ5XzX1KtXj1atWvH2228zYMAAZs+e7ZinuN89eXvJ5uXn50fNmjVvOnN+71WzZk38/PxK5bXFzZPCvRJ65plnCAwM5P333y9wnoyMDN59913+9a9/0aVLF8aMGUN6ejqQ3Q3n7rvvZvr06XTt2pXIyEjGjx/PnDlzeOONN+jYsSMDBgwgJiaGDz/8kG7dunHPPffwyy+/OF7/4MGDPPXUU3Ts2JFOnToxcuRIEhMTS7xMvr6+DBo0iF9//dWRMXdXoa+++oo+ffpw66238tBDD7Ft2zYAIiIiuHjxIpMmTWL8+PEFLltO100Au93OpEmT6NixI3369OHHH390TIuIiODDDz90/J27O9X48ePZu3cvixcvJiIi4rquVsVZ56tXr+buu++mU6dOjBkzhqysrBKvMyGEs9jYWNq3b+8422C1Wnn44YeZMGECkN1lcPny5QwaNIhOnTrx3HPPObVbV65c4d///je333473bt3Z/r06ZjNZiC7K2N4eDjz58+nR48edO3alZkzZ6IoiuP5q1evpk+fPnTu3Jnw8HCOHDnimNa7d29WrlzJkCFDuPXWW3n44Ycd0/Nrx3K3f9LeSnsrhCsdPHiQ8PBwOnXqRO/evfnqq6+cpi9fvpyePXvSpUsXZs6cSUREhFN37Ly6dOlCv379mD59OhaLJd95FEVh6dKl9O3blw4dOjB06FBiYmIc00NDQ/noo4/o0aMHzzzzjKMNXrx4Mbfddht33nknP/zwA5s3b+bee+/ltttuY968eY7nJyUlMXr0aG677Tbat2/PI488wr59+25qPQ0ePJhTp0452qHcXeX37NnDo48+SocOHbj33nsdB0YjIyPZsGEDP/zwA7179y5w2fL2Gvvqq6/o0aMH3bt354MPPnAU5PldgpTTHX79+vXMnz+fAwcOEBoa6jStuOv8u+++46GHHuLWW29lyJAhnD9//qbWmXAmhXsl5O/vz8SJE9mwYQNRUVH5zvPqq68SHR3N4sWLWb58OXFxcbz99tuO6YmJiej1ejZs2EBYWBgAK1eupGvXrnz//fdUqVKFiIgI0tLSWL16NXfeeSfvvvsuqqqi1+sZNWoU//rXv9i0aROfffYZFy5cYNGiRTe1XLfccosjV24nTpxg9uzZTJgwgS1bttC/f39ef/11rl27RmRkJPXr12f8+PG88847BS5bbocPH0ZVVdavX89TTz3F2LFjOXv2bJH53nnnHTp37szw4cOJjIy8bnpR6zznGqf//ve/REZGsnXr1kK/+IQQN6ZFixa8+OKLzJs3j2vXrrF06VLS0tIchTtk7/Q8++yzrFmzBrPZzGuvvQaAxWJh+PDhGI1GvvzySz7++GO2b9/u1N3z6NGjxMbG8vXXXzN58mS++uorxzWPv//+Ox9//DETJkxgw4YN3H333QwfPtzRHR1g/vz5PPfcc2zcuJGqVasyY8YMR6a87VgOaW+lvRXClWJjYxk+fDi33XYbGzZs4LXXXuP999/np59+AmDjxo2Otm316tVcuHChWAXwO++8w5UrV1i2bFm+0xcsWMCyZcscbWbjxo157rnnnNqk3377ja+//trR3hw9epT4+HjWrl3Lgw8+6GiHlyxZwptvvsmSJUs4efIkAG+//TY2m41Vq1bx3XffUb9+/Zu+jKdFixYAnDlzxulxu93O6NGj6dWrF5s3b2by5MksWLCAHTt2MGLECB588EH69evH2rVrC1y2vDZt2sSyZcuYNWsWq1atcnpuQfr378+IESPo0KEDO3fuvG56cdb5/PnzmThxIuvWrSMjI8PpYIi4eVK4V1J9+/bl3nvvZdq0adcNYBETE8PevXuZO3cuHTp0oEOHDrz//vv8+eefnD592jHfc889R3BwsOOawdatWzN06FCaNWvGgAEDMJlMvPPOO7Ro0YKhQ4eSnp5OWloaJpOJUaNG8corr9CkSRO6du3K/ffff11DdqNyulcaDAanxy9evAhkd71q1KgRo0aNYsGCBfj4+FC9enW0Wi1BQUFO3TPzLltuderUYcqUKbRo0YKRI0fStWvXYg3cUaVKFXx8fPD396d69epO04qzzm02GxMnTiQ0NJSePXvSs2dPjh49emMrSYhKbvr06XTu3NnpJ/eZihdeeIGaNWsyadIkFi5cyIwZM6hatapjelhYGI888gitWrVi1qxZHD58mOjoaHbs2MGVK1d4//33ad26NT169GDy5MmsXr2azMxMIHsbnj59Os2bN2fQoEG0bt3asQ0vXbqUF154gb59+9KsWTNeeuklp7P/AI888gh9+/YlJCSEZ599lmPHjgEU2I4B0t5KeyuES61Zs4bQ0FDefPNNQkJCCAsLY+jQoSxduhSAr7/+moiICPr370/Lli2ZO3dusbpe16tXj9dee43Fixdz4cIFp2mqqrJy5UpeffVV+vTpQ4sWLZgxYwbe3t58//33jvkGDx5M8+bNadmyJZB9xnjSpEk0bdqUJ554AqPRyGuvvUZoaCjh4eEEBQU5Dgz26tWLd999lxYtWnDLLbfw9NNPExsbW2S39cIU1G5mZmaSnp5OrVq1aNy4saN3V+vWrQkMDMTPzw+dTufUHT7vsuU1c+ZM2rZtS58+fRg+fDjffPNNkfn8/PwICAjA29v7usufirvOhw8fzh133EGrVq0IDw+XdrOUlc7INaJcmjRpEgMGDGDFihW0bdvW8fjZs2cJDAx0HBmE7KOE1apVIzY2lho1agDZO2a5NWnSxPG7n58ftWvXxtfXF8Dxr8VioX79+oSFhbF8+XKio6M5c+YMJ0+epEOHDje1PDlH/AIDA50ev+uuu2jbtq1jZ7t37948/vjj+Pv7F/haeZctt9DQUKdrktq1a0dsbOxNZS/uOg8ODnZMDwoK8oi7AAhRnrz66qs88MADTo95ef3vGLZOp2PatGk8/fTTPPDAA9x7771O83bp0sXxe5MmTahevTqxsbFcunSJ4OBgpyKxS5cu2O12xwjsNWrUcCpYc2/DsbGxzJs3j48//tgxPae9zP1+uZ+rKAp2u73Q67br1Kkj7W0e0t4KUXpiY2Pp2LGj02OdO3d2dJc/efIkI0eOdEyrVq0aISEhxXrtYcOGsWHDBmbOnMnixYsdj6ekpJCenu70vj4+PrRv396pfcjbttSoUYOgoCAAx8GD3PP4+fk5uuaHh4ezefNmDhw4QFxcnONAqd1uL1b2/OS0mzkZclSvXp2hQ4cybdo0Fi1aRK9evXj44YcLHTuksHbT19fX0dUdoG3btnz22Wclzg3FX+fSbrqWFO6VWOPGjXnxxReJjIxk2rRpjsdziuy87Ha70/WYeefLu/OYe2c4t8TERB577DHatGnDXXfdxZNPPskff/xRYLf94jp58iQNGza8rkH09/dn9erVREVFsW3bNrZs2cLKlSv56quvaN26db6vVdA6gOuXS1EUfHx88p23uA18cdd53ve5mSO/QlRGNWvWpGnTpoXOc/LkSbRaLUePHsVoNBIQEOCYlreds9vteHl55XsGKWf7z9mG82sncrZhu93OuHHjuOuuu5ym537v/AYxKqoNkPa2+O8n7a0QNy6/ti/noCJkt5l5t53ibkve3t5MmTKFoUOH8ttvvxX6npC9DeduB4raTwXQaDT55h8xYgQZGRn079+f3r17Y7VaefXVV4uVuyA53fDzO0v+7rvv8vTTT/Pbb7+xbds2IiIimDlzJo899li+r1VYu5l3mRRFcdz1I7/lLU5xXdx1Lu2ma0lX+Upu5MiR1K1b12mAn5CQEAwGg9MRtDNnzqDX64t9lLQwv/76K4GBgfz3v/9l+PDhdOvWjYSEhJvauC0WCxs3brzuTBpkD5qycOFCunXrxtixY/npp5+oXbs227dvL9F7nTlzxinrkSNHHGdudDqdUxeohISEYr2mq9e5EKJ4EhMT+eCDD3jvvffQ6XR89NFHTtOjo6Mdv587d47MzExCQ0Np3rw558+fdwxwBnDo0CG0Wq3TGYiChISEcOXKFZo2ber4WbZsGXv37r2p5ZH29nrS3gpRepo3b87hw4edHjt48KBjW7rllls4fvy4Y5pery/w/uf56datG2FhYbz33nuOx3JGbM/9vlarlePHj5fKNnzmzBn27dvHZ599xksvvcS9997rGG/kZtrOdevW0a5dO6feUwDJyclMnTqVRo0a8fzzz/P111/z6KOPOsYJyK/YLkxWVpbToHBHjx51tJs+Pj5O7abRaHS6y1RB7+XqdS6KR864V3I6nY4pU6bwzDPPOB5r3rw5vXr1Yty4cUyePBmAadOm0bVrV9q0acOePXtu6j2rV69OUlISf/31F8HBwfz000/88ssvtGnTptivkZaWRkBAAIqicOnSJZYsWYLJZOL555+/bl4/Pz8WLlxIrVq1uOuuu4iJieHy5cu0b98eyO7qefbsWacd7sJcuXKF6dOnM3ToULZs2cKJEyccO/ft27dnw4YNPPzww2g0GiIjI50awcDAQM6fP09KSorTa7p6nQshsun1epKTk6973N/fn6CgIKZNm0a7du0ICwujbt26PP/88wwcONDRtXzlypW0b9+exo0bM2PGDHr06EGLFi0ICQmhWbNmvP3227z55ptkZGQwc+ZM+vfv7+h6XZhnn32WiRMn0rx5c7p27crGjRtZt24dQ4YMKdZyFdSOSXsr7a0QpeHYsWPXnZnt0qULTz31FF988QXz5s0jLCyMw4cPOw2aFhERweTJk2nTpg0tW7bkk08+wWg03lAxOnbsWB588EGnx0aMGMH8+fOpV68ezZo1Y+nS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Hc+eJO+2Fzf/FYfkWyEqJlfmzvIWFBTEvHnzmD9/vrtDuS55/9c0aNCA4OBgBg0axIABA2jRooXTZ3Atxfl8yipvBgQEuGS9omiecclMlLmcrjZnz55l4MCBANx22238/vvvBS5fv359Bg4cyJtvvsmVK1cKXe/GjRvp0aMHERER9OnTx2l99913H/Pnz6dz58706NGD3bt306VLFzZs2ECnTp1o164dK1as4Pfff+fBBx+kdevWTJw40dHNx2AwMHnyZDp27EiLFi3o3r0733//fan2w1NPPUVaWhr79u1zxJjTVej48eP079+fyMhIOnXqxNy5c7HZbGzcuJElS5awf/9+mjVrVui25XTdzPHDDz9w991306ZNG6ZMmYLZbHbssy5dujjFldOd6vfff2fixIlcuHCBZs2acfbs2XxdrYra559++il9+/alZcuW9OrVi0OHDpVqnwlR0ZU0/12LqqoMGDCA/v37O6YtW7aMjh07kpaWxuLFi3nppZeYNGkSrVq1onv37mzbts2xrKIoLF++nPvvv5+IiAgGDBjAsWPHHPObNWvGV199xSOPPELLli3p27cvZ86cccw/ceIEAwcOJCIigm7durFixQrHSdTixYt55ZVXmDlzJm3btqVDhw68//77AIXmsZz8J/lW8q0Qebkyd169epXXXnuNO++8kzZt2jBmzBin88uYmBiefPJJIiIi6Nu3L4sWLSqyFXfSpEls2rSJP//8s9BlDhw4QL9+/YiMjOS+++5z6l4/YcIExo8fz2OPPUb79u05fvw4zZo145tvvuGhhx6iVatWjBkzhqSkJJ555hlatWrFgAEDuHjxomMdy5Yto2vXrrRo0YLOnTuzaNGiEu+b3Dp27EhISAg//vijI8acrvIZGRm8/PLL3HHHHbRp04ZRo0aRkpJS4OdT2LblvuXp5MmT9O7dm5YtW/Lcc89x9uxZgAJvQcrdHb5r164APPDAA2zcuDFfV/mi9nlUVBSvvvoqkZGRdOnS5Zq3RglnUrhXMXXr1mXx4sUA7Nixg9atWxe67KhRo9Dr9SxYsKDA+Rs3bmTmzJkMHz6cTZs20alTJ4YPH865c+ccy2zevJnly5ezYMECtFotqampfP/993zyyScMGzaMN998k3nz5jmumG7evJlffvkFgDlz5hAfH8+KFSv4+uuvadeuHa+99hoW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\n",
      "text/plain": [
       "<Figure size 1008x216 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x1 = numpy.arange(-1, 11.1, 0.1)\n",
    "x2 = numpy.arange(0, 2, 0.1)\n",
    "x3 = numpy.arange(0, 20, 0.1)\n",
    "\n",
    "plt.figure(figsize=(14, 3))\n",
    "plt.subplot(231)\n",
    "plt.title(\"Normal Distribution\", fontsize=14)\n",
    "plt.fill_between(x1, 0, d.probability(x1), color='c')\n",
    "\n",
    "plt.subplot(232)\n",
    "plt.title(\"Exponential Distribution\", fontsize=14)\n",
    "plt.fill_between(x2, 0, d2.probability(x2), color='m')\n",
    "\n",
    "plt.subplot(233)\n",
    "plt.title(\"Log Normal Distribution\", fontsize=14)\n",
    "plt.fill_between(x3, 0, d3.probability(x3), color='g')\n",
    "\n",
    "plt.subplot(234)\n",
    "plt.title(\"Fit Normal Distribution\", fontsize=14)\n",
    "plt.fill_between(x3, 0, d4.probability(x3), color='c')\n",
    "\n",
    "plt.subplot(235)\n",
    "plt.title(\"Fit Exponential Distribution\", fontsize=14)\n",
    "plt.fill_between(x3, 0, d5.probability(x3), color='m')\n",
    "\n",
    "plt.subplot(236)\n",
    "plt.title(\"Fit Log Normal Distribution\", fontsize=14)\n",
    "plt.fill_between(x3, 0, d6.probability(x3), color='g')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Probability / Log Probability\n",
    "\n",
    "All distributions can calculate probabilities and log probabilities using those respective methods. Different distributions will give very different probabilities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.026995483256604804, 0.03368973499542734, 3.7167987868372287e-06)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d.probability(1), d2.probability(1), d3.probability(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A vector of values can also be passed in."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.02699548, 0.19947114, 0.12098536, 0.0647588 , 0.12098536])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d.probability([1, 5, 7, 8, 3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The same works for multivariate data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.026023208688747114, 0.0019422749531612764)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d7.probability([[9, 10, 11]]), d8.probability([[9, 10, 11]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For the independent components distribution the probability is the multiplication of the probabilities for all three dimensions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0019422749531612768"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d8.distributions[0].probability(9) * d8.distributions[1].probability(10) * d8.distributions[2].probability(11)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fitting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Probability distributions can be fit directly to data, as shown above, using the `from_samples` class method. However, a fit distribution can also be fit to new data using the `fit` method. This method uses maximum likelihood estimates to derive new parameters and is not affected by the current values of the distribution unless an inertia is set, which defines the proportion of the original distribution to use, the default being 0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" :\"Distribution\",\n",
       "    \"name\" :\"NormalDistribution\",\n",
       "    \"parameters\" :[\n",
       "        5.906921950798634,\n",
       "        2.000502667681352\n",
       "    ],\n",
       "    \"frozen\" :false\n",
       "}"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = numpy.random.normal(6, 2, size=1000,)\n",
    "\n",
    "d = NormalDistribution(100, 1)\n",
    "d.fit(X)\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" :\"Distribution\",\n",
       "    \"name\" :\"NormalDistribution\",\n",
       "    \"parameters\" :[\n",
       "        52.95346097539932,\n",
       "        1.500251333840676\n",
       "    ],\n",
       "    \"frozen\" :false\n",
       "}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d = NormalDistribution(100, 1)\n",
    "d.fit(X, inertia=0.5)\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The fit method can also be given weights, in which case weighted maximum likelihood estimates are used. This is how expectation-maximization is done for compositional models. In this next example we'll give 50 samples with mean 5 and 50 samples with mean 9 and weight those samples with mean 9 as 4 times more than those with weight 5. If the samples were unweighted one would expect the result to be 7. However, with the higher magnitude samples being weighted more heavily, the result will actually be closer to 9."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" :\"Distribution\",\n",
       "    \"name\" :\"NormalDistribution\",\n",
       "    \"parameters\" :[\n",
       "        8.228881313766124,\n",
       "        2.5257422669054432\n",
       "    ],\n",
       "    \"frozen\" :false\n",
       "}"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = numpy.random.normal(5, 2, size=100,)\n",
    "X[50:] += 4\n",
    "\n",
    "w = numpy.ones(100)\n",
    "w[:50] = 0.25\n",
    "\n",
    "d = NormalDistribution(10, 1)\n",
    "d.fit(X, w)\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Discrete Distributions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A notable deviant from the numerics logic is the Discrete Distribution. Instead of passing parameters as floats, you instead pass in a dictionary where keys can be any objects and values are the probability of them occurring. Internally the objects that are the keys get converted to integer indices to an array whose values are the probability of that integer occuring. All models store a keymap that converts the inputs to those models to the indices of the discrete distribution. If you try to calculate the log probability of an item not present in the distribution, the default behavior is to return negative infinity, or 0.0 probability."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10000000000000002\n",
      "0.5\n",
      "0.0\n"
     ]
    }
   ],
   "source": [
    "d = DiscreteDistribution({'A': 0.1, 'C': 0.25, 'G': 0.50, 'T': 0.15})\n",
    "print(d.probability( 'A'))\n",
    "print(d.probability( 'G'))\n",
    "print(d.probability('????'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Updating a discrete distributon is the same as updating other distributions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "Missing parentheses in call to 'print'. Did you mean print(d.parameters[0])? (<ipython-input-19-7c05880e7290>, line 5)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-19-7c05880e7290>\"\u001b[0;36m, line \u001b[0;32m5\u001b[0m\n\u001b[0;31m    print d.parameters[0]\u001b[0m\n\u001b[0m          ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m Missing parentheses in call to 'print'. Did you mean print(d.parameters[0])?\n"
     ]
    }
   ],
   "source": [
    "X = list('ACGATACACTGAATGACAGCAGTCACTGACAGTAGTACGAGTAGTAGCAGAGAGTAATAAAGAATTAATATATGACACTACGAAAAAAATGCATCG')\n",
    "\n",
    "d.fit(X)\n",
    "\n",
    "print d.parameters[0]\n",
    "print 1. * numpy.unique(X, return_counts=True)[1] / len(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Kernel Density"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Gaussian Kernel Density is a non-parametric distribution that, instead of parameters, stores the data points that it was trained on directly. When initializing a kernel density you simply pass in the points. These points are converted to a probability distribution by essentially dropping some probability distribution on top of each point and then dividing the density by the number of points, ensuring that the area still integrates to 1. We can see this in action with the Gaussian kernel density which drops a normal distribution on each point with standard deviation equal to the bandwidth."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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lVdme7c5R9cA+MuFdMxmPej/+c9/6uTJk/rkk0906NAhvfDCC3r99dezvdus4SwaAH6T9aA/ePCgVq5cKUm67rrr9N///jfbu8xIouAukOTkvhwAOZTph7eJ8iLfp4GyHvSTk5MqKSmZ+bmwsFCnTp1SUVH8XcdiMdm2LUkz/82mveXlWd8HAH9JlD3J8iIXeZVsH7FYLOFtWQ/6kpISRaPRmZ8dx0kY8tLprh8AMH+yfnrl8uXLNTg4KEk6dOiQrrnmmmzvEgBwFst1XTebOzhz1s33338v13X1/PPP66qrrsrmLgEAZ8l60AMAvMU3YwHAcAQ9ABiOoAcAw+V90P/444+6/vrrk54jmm8mJib06KOP6sEHH1RjY6O++eYbr0tKynEchUIhNTY2qqWlRSMjI16XlJapqSlt2rRJzc3NWrNmjfr7+70uKSPHjx/XzTffrB9//NHrUjLyxhtvqLGxUffcc4/6+vq8LictU1NT2rhxo5qamtTc3Oyb3/m3336rlpYWSdLIyIjuv/9+NTc3q7OzU46T/lc68zroJycn1dPTo4ULF3pdSkbeffddrVixQrt371Z3d7f++te/el1SUmcvU7Fx40a98MILXpeUls8//1xlZWXq7e3V22+/rW3btnldUtqmpqYUCoV00UUXeV1KRoaHh/XNN9/o73//uz788EMdPXrU65LS8q9//UunTp3Sxx9/rHXr1unll1/2uqSU3nrrLW3ZsmWmye3u7lZra6t6e3vlum5GjU3eBr3ruuro6NCTTz6piy++2OtyMvLwww+rqalJkjQ9Pa1AIOBxRcnl+zIVidxxxx3asGGDpNPPl8LCQo8rSl9PT4+ampp0+eWXe11KRvbt26drrrlG69at06OPPqpVq1Z5XVJaKisrNT09LcdxNDk5mfRLm/liyZIleu2112Z+jkQiqq2tlSTV19dr//79af9befFo+/r69P7778/aVlFRobvuukt//vOfPaoqPfFqf/7557Vs2TIdO3ZMmzZtUnt7u0fVpSfTZSryRXFxsaTT9T/++ONqbW31uKL0fPrppyovL9fKlSv15ptvel1ORn777TeNjo5q165dOnz4sB577DH94x//kGVZXpeW1KJFi/Tzzz/rzjvv1G+//aZdu3Z5XVJKDQ0NOnz48MzPruvO/J6Li4s1MTGR9r+VF0fyvffeq3vvvXfWttWrV2vPnj3as2ePjh07prVr1+qjjz7yqMLE4tUuSd99952efPJJPf300zOvwvkq02Uq8smRI0e0bt06NTc36+677/a6nLTs2bNHlmXpq6++km3bamtr0+uvv67LLrvM69JSKisrU1VVlRYuXKiqqioFAgGNj4/r0ksv9bq0pN577z3V1dVp48aNOnLkiB566CF98cUXef9u+2wFBf+bgIlGoyotLU37vnl7NH/55Zczf7/11lv1zjvveFhNZn744Qdt2LBBL7/8ct6/I5FOL1Oxd+9e3XXXXb5apuLXX3/V2rVrFQqFdOONN3pdTtrOblhaWlq0detWX4S8JF1//fX64IMP9Je//EW//PKL/vjjD5WVlXldVkqlpaVasGCBJOmSSy7RqVOnND097XFVmamurtbw8LBuuOEGDQ4OasWKFWnfN2+D3s9efPFFnTx5Un/7298kne6Y83kN/tWrV2toaEhNTU0zy1T4wa5du/T7779r586d2rlzp6TTH2D57QNOP7nlllv09ddfa82aNXJdV6FQyBefjTz88MNqb29Xc3Ozpqam9MQTT2jRokVel5WRtrY2dXR0KBwOq6qqSg0NDWnflyUQAMBweXvWDQBgfhD0AGA4gh4ADEfQA4DhCHoAMBxBDwCGI+gBwHD/B0QqQcqe6LxkAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "d = GaussianKernelDensity( [0.5, 1.2, 4.2, 1.9, 5.4, 3.4], bandwidth=1 )\n",
    "d.plot(n=100000, edgecolor='c', color='c', bins=50)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Changing the bandwidth parameter is equivalent to reducing the variance on a Gaussian. It makes the densities more central around the points, but can cause overfitting."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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MDw8HO+Swvbee+9RU1MT7zLCMjk5ya5du9i+fTsVFRX09PTEu6Qlm56epqGhgaqqKqqrq/noo4/iXVLYvvjiC2677TY+/vjjeJcStvvvv5+amhpqampoaGiIdzlhOXToEJWVlfziF7+gu7vb8v5X7G2Kv31rhjNnzvDcc89x4MCBeJe1ZK+++irHjx9n7dq18S4lLMePHycnJ4fnn3+eL7/8kvvuu4877rgj3mUtyYkTJwA4evQog4ODvPDCC0l1zExOTuJ2u1mzZk28SwlbIBAgGAxy+PDheJcStsHBQf7xj3/wpz/9icuXL/PHP/7R8hpW7Ije6lszRNu6devYt29fvMsI2913382TTz4JQDAYJDU1Nc4VLd2dd95Ja2srACMjI2RnZ8e5ovC0t7dTVVXF97///XiXErYPPviAy5cvU1tby0MPPcSZM2fiXdKS9ff3c9NNN7Fz505+9atfcfvtt1tew4od0Yd7a4ZEU15ezoULF+JdRtgyMjKAr7f/E088QV1dXZwrCk9aWhr19fW8++67vPTSS/EuZ8neeustcnNz2bJlC6+88kq8ywnbmjVr2LFjB9u2beOTTz7hkUce4Z133kmK1+t//vMfRkZGOHjwIBcuXOCxxx7jnXfewTAMy2pYsSP6cG/NINFz8eJFHnroIe699162bt0a73LC1t7ezl/+8heam5v573//G+9yluTYsWOcPHmSmpoavF4v9fX1fPbZZ/Eua8kcDgc///nPMQwDh8NBTk5O0tSfk5NDSUkJq1evJj8/n/T0dMbGxiytYcUGvW7NEB+ff/45tbW17Nq1i4qKiniXE5a3336bQ4cOAbB27VoMwyAlJTleQq+99hpdXV0cPnyYgoIC2tvb+d73vhfvspbszTffnLnF+ejoKBMTE0lT/09+8hP+9re/EQwGGR0d5fLly+Tk5Fhaw4odwpaVlTEwMEBVVdXMrRkk9g4ePMilS5fYv38/+/fvB77+YDkZPiC86667aGho4MEHH2RqaorGxsakqNsOKioqaGhooLq6GsMw2Lt3b9K8A//pT3/K3//+dyoqKggGg7jdbss/m9ItEEREbC453neKiEjEFPQiIjanoBcRsTkFvYiIzSnoRURsTkEvImJzCnoREZv7P457ACaXiJuBAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "d = GaussianKernelDensity( [0.5, 1.2, 4.2, 1.9, 5.4, 3.4], bandwidth=0.2 )\n",
    "d.plot(n=100000, edgecolor='c', color='c', bins=50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Passing in weights can change the influence of each sample for the final probability distribution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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SnZZq/LDmRfuW62/0ReQDMnMtmg0uuZrSQ/67OxsRSKRxZ9t214z5KWvRv0AgK2T9GfdlJSUqK+vT5I0PDys/fv3J3uVAIAlLMdxnGSuYOGum48//liO4+jEiRO65ZZbkrlKAMASSQ96AIC3eEwxABiOoAcAwxH0AGA4gj4O27bV3Nysqqoq1dbWanR01OuSEvbee++ptrbW6zISMjc3pyNHjujQoUOqrKxUT0+P1yXFNT8/r4aGBlVXV6umpkYff/yx1yUlbGJiQnfccYc++eQTr0tJ2P3336/a2lrV1taqoaHB63IScv78eVVVVenHP/6xuru7PauDh5rFkaqPcHjxxRd14cIF7d692+tSEnLhwgXl5eXpmWee0RdffKEf/ehH+sEPfuB1WTFdvHhRkvTKK69oaGhIzz77bEr0jbm5OTU3N2vXrl1el5KwaDQqx3HU0dHhdSkJGxoa0l/+8he9/PLLmpmZ0e9//3vPamFEH0cqPcJhqb179+r06dNel5Gwe+65R0888YQkyXEcpaene1xRfHfeeaeOHTsmSRobG1Nubq7HFSWmra1N1dXVuuGGG7wuJWEffvihZmZmdPjwYT300EMaHh72uqS4+vv7tX//fj322GP62c9+pu9973ue1cKIPo71PsLBLyoqKnTlyhWvy0hYVlaWpK/29+OPP666ujqPK0pMRkaG6uvr9c477+i5557zupy43nzzTeXn56usrEwvvPCC1+UkbNeuXXr44Yf1wAMP6NNPP9Ujjzyit99+29fH4b///W+NjY3p3LlzunLlih599FG9/fbbsizL9VoY0cex3kc4YOM+++wzPfTQQ7rvvvt07733el1Owtra2vSHP/xBTU1N+s9//uN1OTG98cYbGhwcVG1trUKhkOrr6zU+Pu51WXEVFBTohz/8oSzLUkFBgfLy8nxfd15enkpLS7Vz504VFhYqMzNTk5OTntRC0MfBIxzc8fnnn+vw4cM6cuSIKisrvS4nIW+99ZbOnz8vSdq9e7csy1Jamr8PqZdeekmdnZ3q6OhQUVGR2tradP3113tdVlyvv/66Tp06JUkKh8Oanp72fd3f/e539e6778pxHIXDYc3MzCgvL8+TWhiaxnHXXXdpYGBA1dXVi49wwNY7d+6cvvzyS509e1Znz56V9NUFZT9fMLz77rvV0NCgBx98UNeuXVNjY6Ov601llZWVamhoUE1NjSzL0okTJ3z/yfr73/++/vznP6uyslKO46i5udmza088AgEADOfvz5kAgE0j6AHAcAQ9ABiOoAcAwxH0AGA4gh4ADEfQA4Dh/h+bSgjXbHnVpwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "d = GaussianKernelDensity( [0.5, 1.2, 4.2, 1.9, 5.4, 3.4], weights=[1, 1, 1, 3, 1, 1], bandwidth=0.2 )\n",
    "d.plot( n=100000, edgecolor='c', color='c', bins=100 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Out-of-core learning\n",
    "\n",
    "Distributions also have the `summarize` and `from_summaries` method that implement out-of-core learning. More will be available in the out-of-core learning tutorial, but the gist is that you can train on an amount of data that doesn't fit in memory and still yield exact updates. This works for any model in pomegranate, but lets illustrate it for an independent components distribution made up of three very different distributions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" : \"Distribution\",\n",
       "    \"name\" : \"IndependentComponentsDistribution\",\n",
       "    \"parameters\" : [\n",
       "        [\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"NormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    15.975331623897382,\n",
       "                    0.9839454537443147\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"ExponentialDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    0.06273786783336628\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"LogNormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    2.7687181529109424,\n",
       "                    0.06401250783319416\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            }\n",
       "        ],\n",
       "        [\n",
       "            1.0,\n",
       "            1.0,\n",
       "            1.0\n",
       "        ]\n",
       "    ],\n",
       "    \"frozen\" : false\n",
       "}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pomegranate import *\n",
    "import numpy\n",
    "\n",
    "X = numpy.random.normal(16, 1, size=(1000, 3))\n",
    "\n",
    "d = IndependentComponentsDistribution([NormalDistribution(5, 1), \n",
    "                                       ExponentialDistribution(7), \n",
    "                                       LogNormalDistribution(0.6, 0.3)])\n",
    "\n",
    "d2 = d.copy()\n",
    "\n",
    "d.summarize(X[:500])\n",
    "d.summarize(X[500:])\n",
    "d.from_summaries()\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" : \"Distribution\",\n",
       "    \"name\" : \"IndependentComponentsDistribution\",\n",
       "    \"parameters\" : [\n",
       "        [\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"NormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    15.975331623897368,\n",
       "                    0.9839454537444303\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"ExponentialDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    0.06273786783336632\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            },\n",
       "            {\n",
       "                \"class\" : \"Distribution\",\n",
       "                \"name\" : \"LogNormalDistribution\",\n",
       "                \"parameters\" : [\n",
       "                    2.7687181529109472,\n",
       "                    0.06401250783306929\n",
       "                ],\n",
       "                \"frozen\" : false\n",
       "            }\n",
       "        ],\n",
       "        [\n",
       "            1.0,\n",
       "            1.0,\n",
       "            1.0\n",
       "        ]\n",
       "    ],\n",
       "    \"frozen\" : false\n",
       "}"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d2.fit(X)\n",
    "d2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also take a look at the JSON serialization. JSONs are the perfect way to store these models given their human interpretability, and the ability to recursively store JSONs within other JSONs, such as more complicated models (such as HMMs) will need to store the JSON of each distribution. It is useful to store these models after the computationally intensive task of training them, so that it need not be repeated."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"class\" : \"Distribution\",\n",
      "    \"name\" : \"IndependentComponentsDistribution\",\n",
      "    \"parameters\" : [\n",
      "        [\n",
      "            {\n",
      "                \"class\" : \"Distribution\",\n",
      "                \"name\" : \"NormalDistribution\",\n",
      "                \"parameters\" : [\n",
      "                    15.975331623897368,\n",
      "                    0.9839454537444303\n",
      "                ],\n",
      "                \"frozen\" : false\n",
      "            },\n",
      "            {\n",
      "                \"class\" : \"Distribution\",\n",
      "                \"name\" : \"ExponentialDistribution\",\n",
      "                \"parameters\" : [\n",
      "                    0.06273786783336632\n",
      "                ],\n",
      "                \"frozen\" : false\n",
      "            },\n",
      "            {\n",
      "                \"class\" : \"Distribution\",\n",
      "                \"name\" : \"LogNormalDistribution\",\n",
      "                \"parameters\" : [\n",
      "                    2.7687181529109472,\n",
      "                    0.06401250783306929\n",
      "                ],\n",
      "                \"frozen\" : false\n",
      "            }\n",
      "        ],\n",
      "        [\n",
      "            1.0,\n",
      "            1.0,\n",
      "            1.0\n",
      "        ]\n",
      "    ],\n",
      "    \"frozen\" : false\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "print(d.to_json())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Serialization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Distributions (except tables right now) support serialization to JSONs using `to_json()` and `Distribution.from_json(json)`. We can see a few examples easily."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"class\" :\"Distribution\",\n",
      "    \"name\" :\"NormalDistribution\",\n",
      "    \"parameters\" :[\n",
      "        5.0,\n",
      "        2.0\n",
      "    ],\n",
      "    \"frozen\" :false\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "print(NormalDistribution(5, 2).to_json())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"class\" :\"Distribution\",\n",
      "    \"dtype\" :\"str\",\n",
      "    \"name\" :\"DiscreteDistribution\",\n",
      "    \"parameters\" :[\n",
      "        {\n",
      "            \"A\" :0.5,\n",
      "            \"B\" :0.25,\n",
      "            \"C\" :0.25\n",
      "        }\n",
      "    ],\n",
      "    \"frozen\" :false\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "print(DiscreteDistribution({'A': 0.5, 'B': 0.25, 'C': 0.25}).to_json())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"class\" :\"Distribution\",\n",
      "    \"name\" :\"GammaDistribution\",\n",
      "    \"parameters\" :[\n",
      "        5.0,\n",
      "        2.0\n",
      "    ],\n",
      "    \"frozen\" :false\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "print(GammaDistribution(5, 2).to_json())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can load them up using the base Distribution class. This is done because, when storing compositional models, they typically don't know what type of distribution is being stored."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.05399096651320961"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "NormalDistribution(1, 1).probability(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.05399096651320961"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Distribution.from_json(NormalDistribution(1, 1).to_json()).probability(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
